package com.itany.shop.servlet;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 石小俊
 */
@WebServlet("*.file")
public class FileServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String path = request.getServletPath();
        switch (path) {
            case "/upload.file":
                upload(request, response);
                break;
            case "/download.file":
                download(request, response);
                break;
            case "/download2.file":
                download2(request, response);
                break;
            default:
                PrintWriter out = response.getWriter();
                out.println("<h1 style='color:red;'>对不起,您访问的资源不存在,请检查请求</h1>");
                break;
        }
    }

    public void upload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取表单数据,无法获取二进制流数据
//        String username = request.getParameter("username");
//        String file = request.getParameter("file");
//        System.out.println("username:"+username+",file:"+file);

        // 获取请求中的二进制数据
//        InputStream in = request.getInputStream();
//        byte[] b = new byte[1024];
//        int i = in.read(b);
//        System.out.println(new String(b, 0, i));

        // 获取解析工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 获取解析器
        ServletFileUpload upload = new ServletFileUpload(factory);

        try {
            // 解析请求
            List<FileItem> fileItems = upload.parseRequest(request);
            Map<String, FileItem> items = new HashMap<>();
            for (FileItem item : fileItems) {
                // 获取用户名
//                if("username".equals(item.getFieldName())){
//                    System.out.println("用户名:"+item.getString());
//                }
//                if("file".equals(item.getFieldName())){
//                    System.out.println("文件名:"+item.getName());
//                    System.out.println("文件内容:"+item.getString("utf-8"));
//                }
                // 由于List集合在使用时需要判断对应元素,比较繁琐
                // 因此,可以将List集合转换成Map集合,表单的name属性值作为key,当前FileItem对象作为value
                items.put(item.getFieldName(), item);
            }
//            System.out.println("用户名:"+items.get("username").getString("utf-8"));
//            System.out.println("文件名:"+items.get("file").getName());
//            System.out.println("文件内容:"+items.get("file").getString());

            FileItem file = items.get("file");
            String fileName = file.getName();
            // 限制不允许上传jsp文件
            if (fileName.endsWith(".jsp")) {
                request.setAttribute("uploadMsg", "不允许上传jsp文件");
                request.getRequestDispatcher("/jsp/upload.jsp").forward(request, response);
                return;
            }


            // 将文件上传到服务器中
            // 1.获取服务器根路径,需要通过application进行获取
            ServletContext application = getServletContext();
            // application.getRealPath(path):获取服务器路径
            // 当参数值为空时,表示根目录
            // 当参数值不为空时,表示根目录+参数指定的目录
//            String path = application.getRealPath("");
            // 我们需要在服务器根目录创建一个专门存储上传的资源的目录upload
            // 在upload中,每天创建一个以年月日命名的子目录,当前的资源存储到对应子目录中
            String path = application.getRealPath("/upload/" + new SimpleDateFormat("yyyyMMdd").format(new Date()));
            System.out.println("path:" + path);
            // 由于服务器初始可能没有该目录,因此必须通过代码进行创建
            File f = new File(path);
            f.mkdirs();


            file.write(new File(path, fileName));
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void download(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取需要下载的资源地址
        String path = getServletContext().getRealPath("/js/jquery-3.4.1.min.js");

        FileInputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(path);
            out = response.getOutputStream();

//            byte[] b = new byte[1024];
//            int i;
//            while ((i = in.read(b)) != -1) {
//                out.write(b, 0, i);
//            }

            response.setHeader("content-disposition", "attachment;filename=jquery-3.4.1.min.js");
            byte[] b = new byte[1024];
            int i;
            while ((i = in.read(b)) != -1) {
                out.write(b, 0, i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void download2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String path = getServletContext().getRealPath("/lib/jstl-1.2.jar");
        FileInputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(path);
            out = response.getOutputStream();

//            byte[] b = new byte[1024];
//            int i;
//            while ((i = in.read(b)) != -1) {
//                out.write(b, 0, i);
//            }

            // 在下载的时候,默认做的是在线打开,可以使用右键选择附件下载
            // 但是这样使用起来还是比较麻烦,因此可以通过设置响应头信息更新默认方式
            // 通过content-disposition属性设置附件方式,其值有两个
            // 1.attachment:附件下载
            // 2.inline:在线打开
//            response.setHeader("content-disposition","attachment");
//            byte[] b = new byte[1024];
//            int i;
//            while ((i = in.read(b)) != -1) {
//                out.write(b, 0, i);
//            }

            // 此时已经可以实现附件下载了,但是又出现了新的问题
            // 此时下载的文件名是当前的请求名
            // 可以自定义文件名,content-disposition属性的值可以由两部分组成
//            response.setHeader("content-disposition","attachment;filename=jstl-1.2.jar");
            // 如果文件名是一个中文,需要转换成ISO-8859-1的字符集
            response.setHeader("content-disposition", new String("attachment;filename=你好.jar".getBytes(), "ISO-8859-1"));
            byte[] b = new byte[1024];
            int i;
            while ((i = in.read(b)) != -1) {
                out.write(b, 0, i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
